//------------------------------------------------------------
//  Filename: video_config.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2017-09-01 19:18
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module CAMERA_CONFIG ( 
    input  wire        clk_100mhz,
    input  wire        rst, 

    input  wire [31:0] camera_pwr_ctrl,
    output reg         camera_resetn,
    output reg         camera_pwrdown,

    input  wire        iic_addr_size, 
    input  wire [7:0]  iic_devid,
    output wire [15:0] iic_data_read,
    output wire        iic_trans_over,
    output wire        iic_sclk,
    inout  wire        iic_sda,

    output reg  [15:0] rom_cfgAddr,
    input  wire [23:0] rom_cfgData,

    output reg  [15:0] ext_cfg_state,
    input  wire [31:0] ext_iic_ctrl
);  
//--------------------------------------------------------
wire       clk = clk_100mhz;
//--------------------------------------------------------
reg[23:0]  InitCfg;
reg[23:0]  dvpInitCfg;
reg        respon_ok;
reg        time_out1;
reg        time_out2;
reg        camera_recfg;
reg        camera_cfg_en;
//--------------------------------------------------------
localparam CFG_IDLE      = 16'h0001;
localparam CFG_PWRUP     = 16'h0002;
localparam CFG_RESET     = 16'h0004;
localparam CFG_START     = 16'h0008;
localparam CFG_ROMADDR   = 16'h0010;
localparam CFG_WIT1      = 16'h0020;
localparam CFG_WIT2      = 16'h0040;
localparam CFG_GETDAT    = 16'h0080;
localparam CFG_SENDDAT   = 16'h0100;
localparam CFG_WITRESP   = 16'h0200;
localparam CFG_DELAY     = 16'h0400;
localparam CFG_NEXT      = 16'h0800; 
localparam CFG_DONE      = 16'h1000; 
//--------------------------------------------------------
reg[15:0]  cur_cfg_state;
reg[15:0]  nxt_cfg_state;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin     
        cur_cfg_state <= CFG_IDLE;        
    end 
    else begin 
        cur_cfg_state <= nxt_cfg_state;        
    end 
end  
//--------------------------------------------------------
//always @(posedge clk ) cur_cfg_state <= CFG_DONE; // FUSION_V1 
//--------------------------------------------------------
always @(*) begin
    case ( cur_cfg_state )
        CFG_IDLE      : begin  
            if(camera_cfg_en) begin
                nxt_cfg_state = CFG_PWRUP;
            end
            else begin
                nxt_cfg_state = cur_cfg_state;
            end
        end 
        CFG_PWRUP     : begin
			if(time_out1) begin
            	nxt_cfg_state = CFG_RESET;
			end
			else begin
				nxt_cfg_state = cur_cfg_state;
			end
        end		
        CFG_RESET     : begin
			if(time_out2&(~camera_recfg)) begin
            	nxt_cfg_state = CFG_START;
			end
			else begin
				nxt_cfg_state = cur_cfg_state;
			end			
        end
        CFG_START     : begin
			if(time_out1) begin
            	nxt_cfg_state = CFG_ROMADDR;
			end
			else begin
				nxt_cfg_state = cur_cfg_state;
			end			
        end
        CFG_ROMADDR   : begin 
            nxt_cfg_state = CFG_WIT1;
        end 
        CFG_WIT1       : begin
            nxt_cfg_state = CFG_WIT2;
        end
        CFG_WIT2       : begin
            nxt_cfg_state = CFG_GETDAT;
        end    
        CFG_GETDAT      : begin
            nxt_cfg_state = CFG_SENDDAT;
        end           
        CFG_SENDDAT   : begin
            if(InitCfg[23:8] == 16'h0) begin
                nxt_cfg_state = CFG_DELAY;
            end 
            else if(InitCfg[23:8] == 16'hffff) begin
                nxt_cfg_state = CFG_DONE;
            end
            else if(time_out2)begin
                nxt_cfg_state = CFG_WITRESP;
            end
            else begin
                nxt_cfg_state = cur_cfg_state;
            end
        end  
        CFG_WITRESP   : begin
            if(respon_ok) begin
                nxt_cfg_state = CFG_DELAY;
            end
            else begin
                nxt_cfg_state = cur_cfg_state;
            end
        end   
        CFG_DELAY     : begin
            if(time_out1) begin
                nxt_cfg_state = CFG_NEXT;
            end
            else begin
                nxt_cfg_state = cur_cfg_state;
            end
        end         
        CFG_NEXT      : begin
            nxt_cfg_state = CFG_ROMADDR;
        end    
        CFG_DONE      : begin
            if(camera_recfg) begin
                nxt_cfg_state = CFG_RESET;
            end
            else begin
                nxt_cfg_state = cur_cfg_state;
            end
        end  
        default: begin
            nxt_cfg_state = CFG_DONE;
        end        
    endcase
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        rom_cfgAddr <= 10'h0;        
    end 
    else if(cur_cfg_state == CFG_RESET)begin 
        rom_cfgAddr <= 10'h0;        
    end     
    else if(cur_cfg_state == CFG_NEXT)begin 
        rom_cfgAddr <= rom_cfgAddr + 10'h1;        
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        InitCfg <= 24'h0;        
    end 
    else if(cur_cfg_state == CFG_GETDAT) begin 
        InitCfg <= rom_cfgData;        
    end 
end 
//--------------------------------------------------------
reg[31:0] inner_iic_ctrl;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        inner_iic_ctrl <= 32'b0;    
    end 
    else if(iic_trans_over) begin
        inner_iic_ctrl <= 32'b0;    
    end
    else if(cur_cfg_state == CFG_SENDDAT)begin 
        inner_iic_ctrl <= {1'b1,7'b0,InitCfg};
    end 
end 
//--------------------------------------------------------
reg[31:0] iic_ctrl;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        iic_ctrl <= 32'b0;        
    end 
    else if(cur_cfg_state == CFG_DONE)begin 
        iic_ctrl <= ext_iic_ctrl;
    end 
    else begin
        iic_ctrl <= inner_iic_ctrl;
    end 
end 
//--------------------------------------------------------
reg[31:0]   tick_cntr1;
reg[31:0]   tick_cntr2;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        tick_cntr1 <= 32'b0;
    end 
	else if(cur_cfg_state == CFG_IDLE) begin
        tick_cntr1 <= {4'h0,8'h50,20'b0};
	end
	else if(cur_cfg_state == CFG_RESET) begin
        tick_cntr1 <= {4'h0,8'h20,20'b0};
	end		
    else if(cur_cfg_state == CFG_WIT2) begin 
        tick_cntr1 <= {14'h0,8'hff,10'b0};
    end
    else if(tick_cntr1 > 0) begin
        tick_cntr1 <= tick_cntr1 - 32'b1;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        tick_cntr2 <= 32'b0;
    end 
	else if(cur_cfg_state == CFG_PWRUP) begin
        tick_cntr2 <= {4'h0,8'h10,20'b0};
	end	
    else if(cur_cfg_state == CFG_GETDAT) begin 
        tick_cntr2 <= {12'h0,8'h1,12'b0};
    end
    else if(tick_cntr2 > 0) begin
        tick_cntr2 <= tick_cntr2 - 32'b1;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        time_out1 <= 1'b0;    
        time_out2 <= 1'b0;    
    end 
    else begin 
        time_out1 <= (tick_cntr1 > 0)?1'b0:1'b1;    
        time_out2 <= (tick_cntr2 > 0)?1'b0:1'b1;    
    end 
end  
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
	if(rst)begin 	
		camera_resetn  <= 1'b0;
		camera_pwrdown <= 1'b1;
        camera_cfg_en  <= 1'b0; 
	    camera_recfg   <= 1'b0;     		
	end 
	else begin
        camera_cfg_en <= camera_pwr_ctrl[8];
        camera_recfg  <= camera_pwr_ctrl[31];	 	
		if(cur_cfg_state == CFG_PWRUP) begin
			camera_resetn  <= 1'b0;
			camera_pwrdown <= 1'b1;		
		end
		else if(cur_cfg_state == CFG_RESET) begin
			camera_resetn  <= 1'b0;
			camera_pwrdown <= 1'b0; 		
		end
		else if(cur_cfg_state == CFG_START) begin
			camera_resetn  <= 1'b1;
			camera_pwrdown <= 1'b0; 		
		end  
		else if(cur_cfg_state == CFG_DONE) begin 
			camera_resetn  <= camera_pwr_ctrl[0];
			camera_pwrdown <= camera_pwr_ctrl[1];		    
		end 
	end    
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        ext_cfg_state <= 16'b0;    
    end 
    else begin 
        ext_cfg_state <= cur_cfg_state;
    end 
end 
//--------------------------------------------------------
always @(posedge clk ) respon_ok <= iic_trans_over;
//--------------------------------------------------------
IIC_CONFIG IIC_CONFIG_inst0( 
    .clk_100mhz     ( clk_100mhz     ) ,
    .rst            ( rst            ) ,
            
    .iic_addr_size  ( iic_addr_size  ) ,
    .iic_devid      ( iic_devid      ) ,
    .iic_ctrl       ( iic_ctrl       ) ,
    .iic_data_read  ( iic_data_read  ) ,
    .iic_trans_over ( iic_trans_over ) ,
            
    .iic_sclk       ( iic_sclk       ) ,
    .iic_sda        ( iic_sda        ) 
);      

endmodule
